Add BitMap component (#10110) - #12360
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a provider-pluggable Blazor BitMap component with C# models/contracts, IJSRuntime extensions, multiple TypeScript map providers (Leaflet, MapLibre/Mapbox GL, OpenLayers, Cesium, ArcGIS, Azure), an OpenLayers loader, bundled Leaflet CSS, SCSS styles, demo pages, navigation, and bUnit tests. Changes BitMap Component
Sequence Diagram(s) sequenceDiagram
participant Blazor as BitMap (C#)
participant JSRuntime as IJSRuntime
participant ProviderJS as BitBlazorUI.<jsObject>
participant MapLib as Map library
Blazor->>JSRuntime: BitMapInit(jsObjectName, id, canvasId, element, dotnetRef, options)
JSRuntime->>ProviderJS: init(id, canvasId, element, dotnetRef, options)
ProviderJS->>MapLib: create map, add layers, attach events
ProviderJS-->>Blazor: OnReady / OnViewChanged / OnClick callbacks
Blazor->>JSRuntime: BitMapAddMarker / BitMapSync / BitMapDispose
JSRuntime->>ProviderJS: corresponding method(id, ...)
Estimated code review effort 🎯 5 (Critical) | ⏱️ ~120 minutes Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Pull request overview
Introduces a new generic, provider-pluggable BitMap<TMapProvider> component in Bit.BlazorUI.Extras with seven map backends (Leaflet, MapLibre GL, Mapbox GL, OpenLayers, ArcGIS, Azure Maps, Cesium), exposing a unified imperative API for markers, vector layers, GeoJSON, tile overlays, and view manipulation, plus a full demo page. Closes #10110.
Changes:
- Adds
BitMapRazor component, supporting types (BitMapLatLng,Bounds,Marker,VectorPathStyle,TileOverlay,ViewState, callback args),IBitMapProvider/BitMapProviderBase, and concrete provider classes for each backend. - Adds the corresponding TypeScript providers (
BitMapLeaflet,BitMapGlBase+ MapLibre/Mapbox wrappers,BitMapOpenLayers,BitMapArcGis,BitMapAzureMaps,BitMapCesium) plus shared helpers, and wires SCSS viaextra-components.scss. - Registers the demo page, navigation entry, JS interop extensions, and ignores
.kiro/.cursoreditor folders.
Reviewed changes
Copilot reviewed 33 out of 40 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor[.cs] | New generic component + imperative API and JSInvokable bridge methods. |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap{LatLng,LatLngBounds,Marker,TileOverlay,VectorPathStyle,ViewState,MarkerDragEndArgs}.cs | Shared domain types/payloads. |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cs, BitMapProviderBase.cs | Provider abstraction and common options. |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/Bit*MapProvider.cs | Seven concrete C# provider configurations. |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMap*.ts | TypeScript runtime adapters (Leaflet, GL base + MapLibre/Mapbox, OpenLayers, ArcGIS, AzureMaps, Cesium, shared helpers). |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cs | Provider-agnostic JS interop helpers. |
| src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scss + Styles/extra-components.scss | Component styles and aggregator. |
| src/BlazorUI/Demo/.../Pages/Components/Extras/Map/BitMapDemo.razor[.cs] | Demo page with 13 examples covering all providers. |
| src/BlazorUI/Demo/.../Shared/MainLayout.razor.NavItems.cs | Adds "Map" entry to demo nav. |
| .gitignore | Ignores .kiro and .cursor editor directories. |
Comments suppressed due to low confidence (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts:156
AddMarkerfirst adds the new feature tos.markerSource, then checks if a marker with the same id already exists and removes it. Because the new feature has just been registered with the same id (f.setId(markerId)),s.markerSource.addFeature(f)may throw an "AssertionError: Feature already added to the source" before the previous entry is cleaned up. Removes.markers[markerId]from the source before adding the new feature, mirroring the pattern used in the other providers.
f.setId(markerId);
f.setStyle(BitMapOpenLayers._markerStyle(ol, opts));
s.markerSource.addFeature(f);
const existing = s.markers[markerId];
if (existing) try { s.markerSource.removeFeature(existing); } catch { /* ignore */ }
s.markers[markerId] = f;
}
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (1)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor (1)
203-203: ⚡ Quick winAdd explicit labels for token/key fields.
Line 203 and Line 233 currently rely on placeholders only. Add
Labelto improve screen-reader clarity and form accessibility.Proposed change
- <BitTextField `@bind-Value`="mapboxToken" Placeholder="pk.eyJ1…" Style="margin-bottom:0.5rem;max-width:480px" /> + <BitTextField Label="Mapbox access token" `@bind-Value`="mapboxToken" Placeholder="pk.eyJ1…" Style="margin-bottom:0.5rem;max-width:480px" /> ... - <BitTextField `@bind-Value`="azureMapsKey" Placeholder="Azure Maps subscription key" Style="margin-bottom:0.5rem;max-width:480px" /> + <BitTextField Label="Azure Maps subscription key" `@bind-Value`="azureMapsKey" Placeholder="Azure Maps subscription key" Style="margin-bottom:0.5rem;max-width:480px" />Also applies to: 233-233
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor` at line 203, Add explicit Label attributes to the BitTextField components that currently only use Placeholder so screen readers can announce them; locate the BitTextField instances bound to mapboxToken (BitTextField `@bind-Value`="mapboxToken") and the other token/key field around the second occurrence (the BitTextField at line ~233) and add a meaningful Label (e.g., Label="Mapbox token" and Label="MapTiler key") to each component so they are accessible to assistive tech.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cs`:
- Around line 302-308: OnProviderSet currently returns early when Provider is
null, which prevents reverting to a default provider after initialization;
change OnProviderSet so that when _initialized is true and Provider is null you
create/assign a default TMapProvider (or call ProviderFactory/default factory)
and proceed to call _js.BitMapSync(JsObject, _Id,
Provider.BuildOptionsPayload()) and set _activeProvider = Provider; ensure the
logic still skips work only when nothing changed (e.g., _activeProvider equals
Provider) but handles the "post-init reset to null" case by reinstating the
default provider and resending options.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scss`:
- Around line 9-13: The CSS rule for .bit-map-canvas removes the browser focus
outline (outline: none), which hides keyboard focus for the focusable map
canvas; restore visible keyboard focus by removing the outline: none declaration
(or replace it with a sensible focus style such as outline: auto or add a
:focus/:focus-visible rule to provide an accessible focus ring) so that the
.bit-map-canvas element shows a clear focus indicator when tabbed to.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cs`:
- Around line 35-41: In BuildOptionsPayload, validate the basemap/key combo
before returning the payload: if BasemapId is not "osm" (case-insensitive) and
ApiKey is null/empty, throw a clear ArgumentException (or
InvalidOperationException) with a message explaining that non‑OSM basemaps
require a valid ApiKey; use the existing GetCommonOptions(), BasemapId and
ApiKey symbols to locate where to add the check so invalid combinations fail
fast rather than emitting a runtime JS config error.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cs`:
- Around line 10-37: The SubscriptionKey property is required but currently can
be empty and is passed into BuildOptionsPayload; update the BuildOptionsPayload
method in BitAzureMapsMapProvider to validate SubscriptionKey
(non-empty/non-whitespace) and throw a clear exception (e.g., ArgumentException)
if it's missing before calling GetCommonOptions; then only add
common["subscriptionKey"] = SubscriptionKey after validation so initialization
fails fast and provides a deterministic error.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 232-267: addGeoJson currently only handles Point, LineString, and
Polygon and silently drops MultiPoint, MultiLineString, MultiPolygon and
GeometryCollection; update addGeoJson to recursively expand multi-geometries and
GeometryCollection into their constituent geometries and create graphics for
each piece using the same attribute merge (props) and existing symbol helpers
(_lineSym, _fillSym, Point symbol); for MultiPoint create a Graphic per
coordinate using esri.Point, for MultiLineString create a Polyline per
coordinate array, for MultiPolygon create one or more Polygon graphics using
rings (maintaining spatialReference { wkid: 4326 }), and for GeometryCollection
iterate its geometries and dispatch by type; keep using esri.Graphic and ensure
all created graphics are added to s.view.graphics and included in
s.geoJsonLayers[layerId] so nothing is silently dropped.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.ts`:
- Around line 265-296: When adding a GeoJSON/vector layer (in addGeoJson and the
similar _addVectorLayer code paths referenced around lines 344-356) we currently
overwrite s.geoJsonLayers[layerId] without removing the previously-added map
layers and source, leaking stale layers; update both functions to first check
s.geoJsonLayers[layerId], and if present iterate its layerIds to remove each
layer from s.map.layers (s.map.layers.remove(...)) and remove the previous
source from s.map.sources (and dispose/clear the DataSource if appropriate),
then delete the registry entry before creating and registering the new
DataSource and layers so removeLayer will correctly clean up the latest
instance.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs`:
- Around line 10-41: The BuildOptionsPayload currently forwards StyleUrl and
AccessToken unchanged which allows a "mapbox://" style to be used with an empty
AccessToken; update BitMapboxMapProvider.BuildOptionsPayload to validate and
guard this: detect when StyleUrl starts with "mapbox://" and if
string.IsNullOrWhiteSpace(AccessToken) either throw a clear ArgumentException
(or return/fallback to a non-mapbox CDN style) so consumers get a deterministic
failure instead of runtime errors; modify the method to check
StyleUrl.StartsWith("mapbox://", StringComparison.OrdinalIgnoreCase) and handle
the empty AccessToken case before adding values to the common dictionary.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts`:
- Around line 258-273: addGeoJson only sets _bmLayerId on the DataSource, but
the click handler expects metadata on each picked Entity, so GeoJSON features
never trigger OnGeoJsonFeatureClick; update BitMapCesium.addGeoJson (and the
similar routine around lines 381-395) to iterate ds.entities.values and for each
entity set entity._bmLayerId = layerId and entity._bmKind = 'geojson' (or
whatever kind the click handler checks), and also apply any per-entity
style/metadata as needed so the pick logic can detect GeoJSON features; keep the
existing DataSource tagging but ensure every Entity gets the same metadata after
GeoJsonDataSource.load completes and before adding to viewer.
- Around line 150-160: The add/remove order is reversed causing Cesium to throw
on duplicate IDs; locate the marker creation blocks (uses s.viewer.entities.add,
id `bm-marker-${id}-${markerId}`, variables ent, existing and
s.markers[markerId]) and remove any existing entity first (check existing =
s.markers[markerId]; if (existing) try { s.viewer.entities.remove(existing); }
catch {/*ignore*/}) before calling s.viewer.entities.add(...) and then assign
s.markers[markerId] = ent; apply the same change to the other similar blocks
referenced (around the ranges mentioned).
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.ts`:
- Around line 292-297: The click handlers attached via s.map.on('click', ...)
(the handler created near lines with layerId/fillId/lineId) are never
unregistered, so update the code to store these handler references in the
vectorCatalog entry for the vector (e.g., keep the handler function(s) under
vectorCatalog[layerId].clickHandler or similar) and then, inside _removeVector,
call s.map.off('click', fillId, handler) and s.map.off('click', lineId, handler)
(or the exact stored handler refs) before removing the layers and source; ensure
you reference the same handler function objects when calling map.off so
listeners are fully removed and will not persist when layers are re-added.
- Line 177: The popup content is being injected unsafely via
setHTML(String(opts.popupHtml)) in BitMapGlBase; guard against XSS by checking
the source and type of opts.popupHtml and either (a) use marker.setPopup(new
gl.Popup({ offset: 25 }).setText(String(opts.popupHtml))) for
untrusted/plain-text input or (b) run opts.popupHtml through a
sanitizer/whitelist before calling setHTML; update the code path that constructs
the Popup in BitMapGlBase to choose setText when content is untrusted or
sanitize/validate the HTML first and only call setHTML when it is known-safe.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts`:
- Around line 34-48: The provider never maps public interaction toggles
(scrollWheelZoom, dragging, doubleClickZoom, keyboardNavigation) into
OpenLayers, so update the ol.Map creation and the sync path to pass and toggle
ol.interaction.defaults based on the component options object (o) — e.g., set
the map option interactions: ol.interaction.defaults({mouseWheelZoom:
o.scrollWheelZoom !== false, dragPan: o.dragging !== false, doubleClickZoom:
o.doubleClickZoom !== false, keyboard: o.keyboardNavigation !== false}) when
constructing the map in init, and in sync (or the equivalent update handler)
enable/disable those interactions on the existing map instance (map) to reflect
changes to o.scrollWheelZoom, o.dragging, o.doubleClickZoom, and
o.keyboardNavigation.
- Around line 230-238: The style function styleFn currently returns ol.Style({
stroke, fill }) for Point and MultiPoint geometries which doesn't render points;
update styleFn to check for 'Point' and 'MultiPoint' types and return an
ol.Style that includes an image (e.g., ol.style.Circle with radius, fill/stroke)
alongside stroke/fill so point features render; modify the branch where you
create new ol.Style({ stroke, fill }) to instead create new ol.Style({ image: /*
Circle style using fill/stroke */, stroke, fill }) ensuring compatibility with
ol.VectorLayer and the existing features variable.
---
Nitpick comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor`:
- Line 203: Add explicit Label attributes to the BitTextField components that
currently only use Placeholder so screen readers can announce them; locate the
BitTextField instances bound to mapboxToken (BitTextField
`@bind-Value`="mapboxToken") and the other token/key field around the second
occurrence (the BitTextField at line ~233) and add a meaningful Label (e.g.,
Label="Mapbox token" and Label="MapTiler key") to each component so they are
accessible to assistive tech.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7aaa1a15-5612-413b-a9bd-8deefa307b2b
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (35)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 9
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs (1)
34-41:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd a null/empty guard for
StyleUrlbeforeStartsWith.Line 36 can throw if
StyleUrlis null at runtime. Validate it first and fail with a deterministic message.Suggested fix
public override object BuildOptionsPayload() { + if (string.IsNullOrWhiteSpace(StyleUrl)) + { + throw new InvalidOperationException("BitMapboxMapProvider: StyleUrl is required."); + } + if (StyleUrl.StartsWith("mapbox://", StringComparison.OrdinalIgnoreCase) && string.IsNullOrWhiteSpace(AccessToken)) { throw new InvalidOperationException( $"BitMapboxMapProvider: An AccessToken is required when using a 'mapbox://' style ('{StyleUrl}'). " + "Provide a valid Mapbox access token or use a non-Mapbox style URL."); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs` around lines 34 - 41, In BuildOptionsPayload, guard against null/empty StyleUrl before calling StyleUrl.StartsWith to avoid a NullReferenceException: check string.IsNullOrWhiteSpace(StyleUrl) first and throw a clear InvalidOperationException (similar to the existing AccessToken check) when StyleUrl is null/empty; only then evaluate StartsWith("mapbox://", StringComparison.OrdinalIgnoreCase) and proceed with the current AccessToken validation (reference: BuildOptionsPayload, StyleUrl, AccessToken).src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cs (1)
37-42:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHarden
BasemapIdvalidation and make OSM check case-insensitive.Line 37 treats
"OSM"as non-OSM and may enforceApiKeyincorrectly. Also guard emptyBasemapIdearly.Suggested fix
public override object BuildOptionsPayload() { - if (BasemapId is not "osm" && string.IsNullOrWhiteSpace(ApiKey)) + if (string.IsNullOrWhiteSpace(BasemapId)) + { + throw new InvalidOperationException("BitArcGisMapProvider: BasemapId is required."); + } + + if (!string.Equals(BasemapId, "osm", StringComparison.OrdinalIgnoreCase) && string.IsNullOrWhiteSpace(ApiKey)) { throw new InvalidOperationException( $"BitArcGisMapProvider: An ApiKey is required for the '{BasemapId}' basemap. " + "Only the 'osm' basemap works without an API key."); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cs` around lines 37 - 42, Validate BasemapId in BitArcGisMapProvider by first guarding against null/empty/whitespace (throwing a clear InvalidOperationException if missing), then perform the OSM check using a case-insensitive comparison (e.g., compare BasemapId to "osm" with StringComparison.OrdinalIgnoreCase or normalize with ToLowerInvariant/Trim) so values like "OSM" or extra whitespace don't incorrectly require an ApiKey, and only throw the existing ApiKey-required InvalidOperationException when the normalized BasemapId is not "osm" and ApiKey is null/whitespace.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cs`:
- Around line 14-22: The Opacity and FillOpacity properties on
BitMapVectorPathStyle accept any double but are documented as 0–1; clamp their
values to the valid range by implementing bounded setters for Opacity and
FillOpacity (or validate and clamp right before serialization) so any assigned
value <0 becomes 0 and >1 becomes 1; update the property implementations on the
BitMapVectorPathStyle class (the Opacity and FillOpacity members) to enforce
this clamping and preserve existing defaults.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cs`:
- Around line 65-82: In BuildOptionsPayload, enforce Cesium token-dependent
options before returning the payload: check IonAccessToken (in
BuildOptionsPayload) and if it's null/empty disable token-required features (set
TerrainEnabled to false and override any Bing/ion-dependent ImageryStyle to a
safe default) so the payload never enables terrain or Bing imagery when
IonAccessToken is missing; update the logic around the TerrainEnabled,
ImageryStyle and IonAccessToken assignments in BuildOptionsPayload accordingly.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 64-72: BitMapArcGis.sync currently updates
center/zoom/basemap/scale but doesn't reapply interaction flags (e.g.,
scrollWheelZoom, dragging) that init sets, so update BitMapArcGis.sync to read
the same options (o.scrollWheelZoom, o.dragging or their exact names used in
init) and reapply them to the stored map/view instance s (the same
enable/disable logic used in BitMapArcGis.init), ensuring interaction state is
toggled on s.view or s.map the same way as during initialization; reference
BitMapArcGis.sync, BitMapArcGis.init, BitMapArcGis._maps and
BitMapArcGis._ensureScaleBar when making the change.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.ts`:
- Around line 318-327: The addTileOverlay implementation
(BitMapAzureMaps.addTileOverlay) currently overwrites s.tileOverlays[opts.id]
without removing any previous layer; before creating the new TileLayer (tlId),
check s.tileOverlays[opts.id] for an existing layer id, locate that layer in
s.map.layers (by the stored layer id) and remove it from the map (and from the
registry) so you don't leave stale state, then proceed to create and add the new
TileLayer and set s.tileOverlays[opts.id] = tlId.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts`:
- Around line 133-143: The SetView and FlyTo methods always default zoom to 4,
causing unintended zoom changes when zoom is omitted; change them to preserve
the current camera altitude when zoom is null by reading the current camera
height (e.g. from s.viewer.camera.positionCartographic.height or equivalent) and
only call BitMapCesium._zoomToAltitude when zoom is provided. Update both
BitMapCesium.setView and BitMapCesium.flyTo to compute altitude = zoom != null ?
BitMapCesium._zoomToAltitude(zoom) : currentCameraHeight and use that altitude
for Cesium.Cartesian3.fromDegrees.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.ts`:
- Around line 328-344: The addTileOverlay method currently returns early when a
source already exists, so new URL/opacity/maxZoom aren't applied; modify
addTileOverlay (and use the instance from BitMapGlBase._require) to detect
existing tileOverlayCatalog[opts.id] or s.map.getSource(sourceId) and remove the
old layer and source (s.map.removeLayer(layerId) and
s.map.removeSource(sourceId)) before adding the new source and layer, or
alternatively update the existing layer's paint and source options via
s.map.setPaintProperty and by recreating the source with the new tiles/maxzoom;
ensure you keep tileOverlayCatalog[opts.id] in sync with the new
sourceId/layerId after replacing/updating so subsequent calls reflect the new
URL/opacity/maxZoom.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.ts`:
- Around line 90-93: The sync currently forces a hardcoded center by building c
= [o.center?.lat ?? 51.505, o.center?.lng ?? -0.09] and always calling
s.map.setView(c, z), which can jump the map on option-only updates; change sync
so it only calls s.map.setView when options.center is explicitly provided (use
o.center and o.zoom or fall back to current s.map.getZoom for the z argument),
and if only options.zoom is provided call s.map.setZoom(o.zoom, { animate: false
}) instead of rebuilding a default center; reference variables/methods:
function/method sync in BitMapLeaflet.ts, variables o.center, o.zoom, c, z, and
calls s.map.setView / s.map.setZoom.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts`:
- Line 181: BitMapOpenLayers.openMarkerPopup currently silently no-ops; change
it to surface a clear failure by throwing a descriptive Error (or at minimum
logging and throwing) so caller code knows OpenLayers doesn't support this
built-in popup behavior; update the method BitMapOpenLayers.openMarkerPopup to
throw an Error that includes context (the passed _id and _markerId and that
OpenLayers requires a custom overlay/implementation) so provider-agnostic
callers receive a visible failure instead of silent no-op.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.ts`:
- Around line 45-53: The circleRingLngLat function can divide by points causing
NaN when points <= 0; add a guard at the start of circleRingLngLat to validate
and normalize points (e.g., if points is not a positive integer, set points =
Math.max(1, Math.floor(points)) or throw a clear error) before using it in the
bearing calculation and loop; ensure the rest of the function uses the
normalized points variable so the division (bearing = (i / points) * 2 *
Math.PI) and loop bounds are safe.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cs`:
- Around line 37-42: Validate BasemapId in BitArcGisMapProvider by first
guarding against null/empty/whitespace (throwing a clear
InvalidOperationException if missing), then perform the OSM check using a
case-insensitive comparison (e.g., compare BasemapId to "osm" with
StringComparison.OrdinalIgnoreCase or normalize with ToLowerInvariant/Trim) so
values like "OSM" or extra whitespace don't incorrectly require an ApiKey, and
only throw the existing ApiKey-required InvalidOperationException when the
normalized BasemapId is not "osm" and ApiKey is null/whitespace.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs`:
- Around line 34-41: In BuildOptionsPayload, guard against null/empty StyleUrl
before calling StyleUrl.StartsWith to avoid a NullReferenceException: check
string.IsNullOrWhiteSpace(StyleUrl) first and throw a clear
InvalidOperationException (similar to the existing AccessToken check) when
StyleUrl is null/empty; only then evaluate StartsWith("mapbox://",
StringComparison.OrdinalIgnoreCase) and proceed with the current AccessToken
validation (reference: BuildOptionsPayload, StyleUrl, AccessToken).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5edad8b8-6807-4608-8452-a84d84564da4
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (35)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs (1)
34-37:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd a null/empty guard for
StyleUrlbeforeStartsWith.
StartsWithon a nullStyleUrlcauses an immediate runtime failure instead of a clear configuration error.Proposed fix
public override object BuildOptionsPayload() { + if (string.IsNullOrWhiteSpace(StyleUrl)) + { + throw new InvalidOperationException("BitMapboxMapProvider: StyleUrl is required."); + } + if (StyleUrl.StartsWith("mapbox://", StringComparison.OrdinalIgnoreCase) && string.IsNullOrWhiteSpace(AccessToken)) { throw new InvalidOperationException( $"BitMapboxMapProvider: An AccessToken is required when using a 'mapbox://' style ('{StyleUrl}'). " + "Provide a valid Mapbox access token or use a non-Mapbox style URL."); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs` around lines 34 - 37, In BuildOptionsPayload(), guard StyleUrl for null/empty before calling StyleUrl.StartsWith(...) — e.g., check string.IsNullOrWhiteSpace(StyleUrl) first and handle it (throw a clear configuration exception or return an appropriate error) so the subsequent StartsWith call is never invoked on null; also retain the existing AccessToken check and ensure the error message references StyleUrl and AccessToken for clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cs`:
- Around line 67-77: The code treats whitespace-only IonAccessToken as present;
update the token presence check in the BitCesiumMapProvider by replacing
string.IsNullOrEmpty(IonAccessToken) with
string.IsNullOrWhiteSpace(IonAccessToken) (i.e., compute hasToken =
!string.IsNullOrWhiteSpace(IonAccessToken)) so TerrainEnabled/terrainEnabled and
imageryStyle logic correctly treat whitespace tokens as missing, and ensure
common["ionAccessToken"] is only set when hasToken is true (otherwise leave it
null/empty).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cs`:
- Around line 20-21: The TileOpacity property on BitLeafletMapProvider currently
allows any double but is documented as 0–1; update the TileOpacity property
setter (the TileOpacity auto-property) to clamp incoming values to the [0,1]
range (e.g., set to 0 if value < 0, to 1 if value > 1, otherwise keep value) so
the component honors its documented contract and use that clamped value
internally when raising any change notifications or rendering updates.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 323-335: In addTileOverlay (BitMapArcGis.addTileOverlay) remove
any existing tile layer from s.tileOverlays[opts.id] (and call s.map.remove on
it) before creating/adding the new esri.WebTileLayer; use
BitMapArcGis._require(id) to get s, check const existing =
s.tileOverlays[opts.id] and if present call s.map.remove(existing) and clear
s.tileOverlays[opts.id] before instantiating tl and calling s.map.add(tl), then
assign s.tileOverlays[opts.id] = tl.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cs`:
- Around line 19-20: TileOpacity currently allows values outside the documented
0–1 range; change the auto-property to use a private backing field and clamp
assignments in the TileOpacity setter (e.g., use Math.Clamp(value, 0.0, 1.0)) so
any set (including the default) is constrained to 0..1 and keep the default at
1.0; update references to the property if they relied on direct field access.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cs`:
- Around line 34-37: In BuildOptionsPayload(), guard StyleUrl for null/empty
before calling StyleUrl.StartsWith(...) — e.g., check
string.IsNullOrWhiteSpace(StyleUrl) first and handle it (throw a clear
configuration exception or return an appropriate error) so the subsequent
StartsWith call is never invoked on null; also retain the existing AccessToken
check and ensure the error message references StyleUrl and AccessToken for
clarity.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 581b08e6-756e-448c-8bbc-f77f5a867969
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (35)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-7:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRemove
.scssextension from the Sass import.Line 7 currently violates
scss/load-partial-extensionand can fail linting.🔧 Suggested fix
-@import "../Components/Map/BitMap.scss"; +@import "../Components/Map/BitMap";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` at line 7, The Sass import in extra-components.scss uses a filename with the .scss extension which violates scss/load-partial-extension; update the import statement that currently references "../Components/Map/BitMap.scss" to omit the .scss extension (use "../Components/Map/BitMap") so the linter accepts the partial import.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cs (1)
772-804:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep
example7CsharpCodealigned with the real overlay-reset behavior.The live
BuildAdvancedProvider()resetsadvOverlayOn, but the displayed snippet doesn’t; copied sample code can leave the toggle state out of sync after provider rebuilds.🧩 Suggested snippet fix
private BitLeafletMapProvider BuildAdvancedProvider() { advProvider = new BitLeafletMapProvider { Center = new(51.5074, -0.1278), Zoom = 11, ScrollWheelZoom = advScrollWheel, Dragging = advDragging, ShowScaleControl = advScaleBar, MaxBounds = advMaxBounds ? new BitMapLatLngBounds(new(51.25, -0.55), new(51.75, 0.35)) : null, }; + advOverlayOn = false; return advProvider; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cs` around lines 772 - 804, The sample string example7CsharpCode is out of sync with the real BuildAdvancedProvider behavior because the live BuildAdvancedProvider resets advOverlayOn when rebuilding the provider but the displayed snippet does not; update the example7CsharpCode snippet to show the same reset logic by modifying the BuildAdvancedProvider code in the snippet to set advOverlayOn = false (or the real reset behavior) when creating the new advProvider, ensuring the displayed BuildAdvancedProvider matches the runtime method and keeps advOverlayOn consistent after provider rebuilds.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor (1)
3-5:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPolish the
PageOutletdescription text.The current text is grammatically awkward and uses inconsistent casing.
✏️ Suggested fix
<PageOutlet Url="components/map" Title="Map" - Description="map component of the bit BlazorUI components" /> + Description="Map component for Bit BlazorUI components." />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor` around lines 3 - 5, Update the PageOutlet component's Description attribute to a polished, grammatically correct string: replace Description="map component of the bit BlazorUI components" with a properly cased sentence such as Description="Map component of the Bit BlazorUI components." (edit the PageOutlet element where Url="components/map" and Title="Map").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cs`:
- Around line 11-14: Update the XML doc comment on BitMapLatLngBounds to mention
both bypass paths: note that because BitMapLatLngBounds is a record struct,
using with-expressions and using object initializers that assign init properties
both bypass the validating constructor (the instance is created first and then
init members are set), and state that validation is enforced when constructing
via the constructor new BitMapLatLngBounds(southWest, northEast); keep the
existing with-expression wording and add the init-property/object-initializer
explanation and the explicit constructor reminder.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 33-38: The ArcGIS provider in BitMapArcGis.ts silently ignores the
public options doubleClickZoom and keyboardNavigation; update the
navigation.actionMap block (and the similar block around lines 81-89) to either
apply those flags to ArcGIS equivalents or explicitly disable/reject them: read
o.doubleClickZoom and set the appropriate actionMap entry (e.g., map
doubleClickZoom to 'zoom' or null) and read o.keyboardNavigation to
enable/disable keyboard actions, or throw/log an explicit unsupported-option
error so callers aren’t silently ignored; modify the navigation.actionMap logic
that currently uses o.scrollWheelZoom and o.dragging to include
o.doubleClickZoom and o.keyboardNavigation handling.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.ts`:
- Around line 105-107: The queued notify callback can run after teardown and
call a disposed .NET object; to fix, add a disposal guard: store a boolean
(e.g., this._isDisposed = false) on the BitMapGlBase instance, set it true in
your component teardown/dispose method, and update the notify lambda to check
the guard and dotnetObj before invoking (e.g., queueMicrotask(() => { if
(this._isDisposed || !dotnetObj) return;
dotnetObj.invokeMethodAsync('OnViewChanged', BitMapGlBase._readView(map)); }));
also ensure you remove the map listeners on dispose (map.off('moveend', notify);
map.off('zoomend', notify);) so no callbacks remain after disposal.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts`:
- Around line 563-569: The dashArray parsing in BitMapOpenLayers._stroke
currently only splits on commas so whitespace-separated values like "4 2" become
a single value; update the split logic in BitMapOpenLayers._stroke (where it
builds lineDash from st.dashArray) to split on commas or whitespace (e.g. use
st.dashArray.split(/[,\s]+/)), then map each token with parseFloat and filter
out empty/NaN entries so both "4,2" and "4 2" parse to [4,2]; keep the rest of
the Stroke construction unchanged.
- Around line 662-664: The event handler for map.on('moveend') captures the
outer dn and can invoke a disposed handle inside queueMicrotask; snapshot the
.NET handle into a local const (e.g., const capturedDn = dn) before calling
queueMicrotask, then inside the microtask check capturedDn is non-null and call
capturedDn.invokeMethodAsync('OnViewChanged', BitMapOpenLayers._readView(s));
this ensures the microtask uses the captured handle and avoids invoking a
disposed dn.
---
Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Line 7: The Sass import in extra-components.scss uses a filename with the
.scss extension which violates scss/load-partial-extension; update the import
statement that currently references "../Components/Map/BitMap.scss" to omit the
.scss extension (use "../Components/Map/BitMap") so the linter accepts the
partial import.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor`:
- Around line 3-5: Update the PageOutlet component's Description attribute to a
polished, grammatically correct string: replace Description="map component of
the bit BlazorUI components" with a properly cased sentence such as
Description="Map component of the Bit BlazorUI components." (edit the PageOutlet
element where Url="components/map" and Title="Map").
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cs`:
- Around line 772-804: The sample string example7CsharpCode is out of sync with
the real BuildAdvancedProvider behavior because the live BuildAdvancedProvider
resets advOverlayOn when rebuilding the provider but the displayed snippet does
not; update the example7CsharpCode snippet to show the same reset logic by
modifying the BuildAdvancedProvider code in the snippet to set advOverlayOn =
false (or the real reset behavior) when creating the new advProvider, ensuring
the displayed BuildAdvancedProvider matches the runtime method and keeps
advOverlayOn consistent after provider rebuilds.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7cdf6642-466b-4e81-aaf0-62efd2005353
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (41)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapInteropErrorArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTooltipDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapValidation.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/openlayers/bit-map-ol-loader.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/Map/BitMapTests.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cs`:
- Around line 37-54: Trim BasemapId and ApiKey before validation and before
putting them into the payload: call Trim/TrimInvariant on BasemapId and ApiKey
at the start of the provider logic that performs validation (the checks using
BasemapId and ApiKey) and then use the trimmed values when setting
common["basemapId"] and common["apiKey"]; ensure string.Equals against "osm"
uses the trimmed BasemapId. This ensures inputs like " osm " are treated as
"osm" and payload/validation are consistent for GetCommonOptions and the Map
provider.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 61-65: Wrap the await view.when() call in a try/catch and, on
rejection, rollback the partially created state by removing
BitMapArcGis._maps[id] and tearing down the created MapView/state: call
view.destroy() (or view?.destroy?.()) and any state cleanup (remove layers,
remove event handlers wired by BitMapArcGis._wireEvents) so the stale instance
is not left registered; rethrow the error after cleanup so initialization still
fails upstream. Ensure you reference the same symbols:
BitMapArcGis._ensureScaleBar, BitMapArcGis._wireEvents, BitMapArcGis._maps[id],
and view.when() when making the change.
- Around line 108-117: The dispose method (BitMapArcGis.dispose) currently only
destroys the ArcGIS view but doesn't remove DOM event listeners added by
_applyInteractivity, leaving stale dblclick/keydown handlers attached to the
container; update _applyInteractivity to store the actual handler functions
(e.g., onDoubleClick/onKeyDown) on the map instance object
(BitMapArcGis._maps[id].containerHandlers or similar) when adding them with
addEventListener, and then in BitMapArcGis.dispose remove those listeners via
removeEventListener before destroying the view and deleting the map entry so the
container is fully cleaned up.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts`:
- Around line 260-266: The code in _applyImagery() currently always removes
imageryLayers.get(0) which can be a user overlay; change logic to track and
remove only the stored base layer (_baseImageryLayer) instead of unconditionally
removing index 0, initialize _baseImageryLayer in init() from the viewer's
initial base layer (when present) so subsequent calls to _applyImagery()
replace/remove that specific layer, and ensure addTileOverlay() adds overlays
without altering _baseImageryLayer.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cs`:
- Around line 875-898: Update the example5CsharpCode string so it exactly
mirrors the real SetTileProvider implementation: ensure the "carto" branch in
example5CsharpCode sets TileAttribution to "© OSM © CARTO" and
restore/add the TileAttribution property in the "topo" branch to match the live
demo's attribution (the same string used by the actual SetTileProvider for
BitLeafletMapProvider.TileAttribution). This keeps example5CsharpCode consistent
with the SetTileProvider method and preserves required map credits.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a7746b2b-0205-483e-9c79-881b680fc092
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (41)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapInteropErrorArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTooltipDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapValidation.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/openlayers/bit-map-ol-loader.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/Map/BitMapTests.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts (1)
73-78:⚠️ Potential issue | 🟠 MajorRestore the original
tabindexin both cleanup paths.
_applyInteractivity()can persist__bmPrevTabIndexand forcetabindex="-1", but the init-failure rollback anddispose()only remove listeners. After a failed init or provider swap, the container can stay non-focusable and the next map instance inherits broken keyboard access.Suggested fix
if (container) { const view = s.view as any; if (view.__bmDblClickHandler) { try { container.removeEventListener('dblclick', view.__bmDblClickHandler, true); } catch { /* ignore */ } view.__bmDblClickHandler = null; } if (view.__bmKeyHandler) { try { container.removeEventListener('keydown', view.__bmKeyHandler, true); } catch { /* ignore */ } view.__bmKeyHandler = null; } + if (view.__bmPrevTabIndex !== undefined) { + try { + if (view.__bmPrevTabIndex === null) container.removeAttribute('tabindex'); + else container.setAttribute('tabindex', view.__bmPrevTabIndex); + } catch { /* ignore */ } + view.__bmPrevTabIndex = undefined; + } }Apply the same reset in the
view.when()rollback block above.Also applies to: 134-145
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts` around lines 73 - 78, The cleanup currently removes only event listeners (dblHandler/keyHandler) but does not restore the previous tabindex set by _applyInteractivity (stored in __bmPrevTabIndex), leaving the container non-focusable after init failure or dispose; update both the view.when() rollback block and the dispose() cleanup (the block that references dblHandler and keyHandler) to read (view as any).__bmPrevTabIndex and if defined restore it to element.tabIndex (or remove the tabindex attribute when it was originally absent) so the original focusability is restored after rollback/dispose.src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts (1)
657-665:⚠️ Potential issue | 🟠 MajorGuard the queued
OnViewChangedinvoke after disposal.Capturing
viewfixed the destroyed-view read, but the microtask still unconditionally calls the captured .NET handle. Ifdispose()runs after_notifyView()schedules the microtask, this can still reject against a disposed handle.Suggested fix
private static _notifyView(s: any) { if (!s.dotnetObj) return; // Capture the view snapshot synchronously. dispose() can destroy s.viewer // and null s.dotnetObj before this microtask runs, so deferring _readView // would risk reading from a destroyed Cesium Viewer. We snapshot the // dotnet handle and the view payload here while everything is still alive. const dotnet = s.dotnetObj; const view = BitMapCesium._readView(s); - queueMicrotask(() => dotnet.invokeMethodAsync('OnViewChanged', view)); + queueMicrotask(() => { + if (s.dotnetObj !== dotnet) return; + void dotnet.invokeMethodAsync('OnViewChanged', view).catch(() => {}); + }); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts` around lines 657 - 665, The microtask unconditionally calls the captured .NET handle even if dispose() ran later; modify _notifyView to capture both dotnet and the source object (s) and, inside the queued microtask, verify the handle is still current (e.g., if (s.dotnetObj === dotnet) dotnet.invokeMethodAsync('OnViewChanged', view)) or otherwise skip the call; alternatively wrap the invokeMethodAsync in a try/catch and silently ignore errors from a disposed handle—update the _notifyView implementation (references: _notifyView, dotnetObj, _readView, OnViewChanged, dispose) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cs`:
- Around line 203-205: The code currently updates the in-memory replay
dictionaries (_markerState, _vectorState, _tileOverlayState) before calling
SafeInvokeAsync (e.g. BitMapAddMarker via JsObject in AddMarker), which can hide
interop failures; change each affected method so the dictionary mutation is
performed only after SafeInvokeAsync completes successfully (await the call and
then add/remove/clear the entry), or if you prefer to keep the pre-mutation,
wrap SafeInvokeAsync in try/catch and roll back the dictionary change on any
exception; apply this pattern consistently to all methods touching
_markerState/_vectorState/_tileOverlayState (the Add*/Remove*/Clear* flows) so
ReplayStateOnProviderSwap remains in sync with the real map.
---
Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.ts`:
- Around line 73-78: The cleanup currently removes only event listeners
(dblHandler/keyHandler) but does not restore the previous tabindex set by
_applyInteractivity (stored in __bmPrevTabIndex), leaving the container
non-focusable after init failure or dispose; update both the view.when()
rollback block and the dispose() cleanup (the block that references dblHandler
and keyHandler) to read (view as any).__bmPrevTabIndex and if defined restore it
to element.tabIndex (or remove the tabindex attribute when it was originally
absent) so the original focusability is restored after rollback/dispose.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.ts`:
- Around line 657-665: The microtask unconditionally calls the captured .NET
handle even if dispose() ran later; modify _notifyView to capture both dotnet
and the source object (s) and, inside the queued microtask, verify the handle is
still current (e.g., if (s.dotnetObj === dotnet)
dotnet.invokeMethodAsync('OnViewChanged', view)) or otherwise skip the call;
alternatively wrap the invokeMethodAsync in a try/catch and silently ignore
errors from a disposed handle—update the _notifyView implementation (references:
_notifyView, dotnetObj, _readView, OnViewChanged, dispose) accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5177733e-e49d-4063-820f-066ee8bb8834
⛔ Files ignored due to path filters (5)
src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/layers.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon-2x.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-icon.pngis excluded by!**/*.pngsrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/images/marker-shadow.pngis excluded by!**/*.png
📒 Files selected for processing (41)
.gitignoresrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMap.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapInteropErrorArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLng.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapLatLngBounds.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarker.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapMarkerDragEndArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapProviderBase.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTileOverlay.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapTooltipDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapValidation.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapVectorPathStyle.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/BitMapViewState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/IBitMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitArcGisMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitAzureMapsMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitCesiumMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitLeafletMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapArcGis.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapAzureMaps.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapCesium.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapGlBase.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLibreMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapLibre.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapMapbox.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapShared.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapboxMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitOpenLayersMapProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/leaflet/leaflet-1.9.4.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/openlayers/bit-map-ol-loader.jssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/Map/BitMapTests.cs
closes #10110
Summary by CodeRabbit
New Features
Documentation / Demos
Style
Tests
Chores